<?php
/**
 * @link https://ym2.cleverstone.top
 * @copyright Copyright (c) 2020 Yii Manager Software LLC
 */

namespace builder\base;

use Yii;
use yii\db\Query;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use builder\behaviors\DatetimeBehavior;

/**
 * 模型继承类
 * @property-read string $error 验证失败,错误提示语
 * @author cleverstone
 * @since ym2.0
 */
class BaseActiveRecord extends ActiveRecord
{
    /**
     * Returns a list of behaviors that this component should behave as.
     *
     * Child classes may override this method to specify the behaviors they want to behave as.
     *
     * The return value of this method should be an array of behavior objects or configurations
     * indexed by behavior names. A behavior configuration can be either a string specifying
     * the behavior class or an array of the following structure:
     *
     * ```php
     * 'behaviorName' => [
     *     'class' => 'BehaviorClass',
     *     'property1' => 'value1',
     *     'property2' => 'value2',
     * ]
     * ```
     *
     * Note that a behavior class must extend from [[Behavior]]. Behaviors can be attached using a name or anonymously.
     * When a name is used as the array key, using this name, the behavior can later be retrieved using [[getBehavior()]]
     * or be detached using [[detachBehavior()]]. Anonymous behaviors can not be retrieved or detached.
     *
     * Behaviors declared in this method will be attached to the component automatically (on demand).
     *
     * @return array the behavior configurations.
     */
    public function behaviors()
    {
        return [
            // 日期自动写入
            'timestampBehavior' => [
                'class' => DatetimeBehavior::class,
                'attributes' => [
                    self::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                    self::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
            ],
        ];
    }

    /**
     * 获取当前模型映射的`ActiveQuery`对象[关联查询必须声明关联关系, 调用*?with方法, 否则附表结果无法通过安全检查，附表结果无法显示! 但是, 可以通过`asArray`方法直接通过数组返回!!]
     * 在ActiveQuery中封装的模型关联查询方法, 个人觉得比较鸡肋, 性能也比较差!!! 不建议使用!!!!
     * @param array|string $select 查询字段
     * @return ActiveQuery
     */
    public static function activeQuery($select = '*')
    {
        return self::find()->select($select);
    }

    /**
     * 重构find方法
     * @return ActiveQuery
     */
    public static function find()
    {
        $activeQueryClass = get_called_class() . 'Query';

        if (class_exists($activeQueryClass)) {
            $activeQueryInstance = Yii::createObject($activeQueryClass, [get_called_class()]);
            if ($activeQueryInstance instanceof ActiveQuery) {
                return $activeQueryInstance;
            }
        }

        return parent::find();
    }

    /**
     * 获取db中的`Query`对象[关联查询，不用声明关联关系] (强烈推荐使用该方法)
     * @param array|string $select 查询字段
     * @param string 主表别名
     * @return Query
     * @throws
     */
    public static function query($select = '*', $alias = '')
    {
        /* @var Query $query */
        $query = Yii::createObject(Query::class);

        if (empty($alias)) {
            return $query->from(static::tableName())->select($select);
        }

        return $query->from([$alias => static::tableName()])->select($select);
    }

    /**
     * 获取验证失败提示[字符串格式]
     * @return string
     */
    public function getError()
    {
        $firstErrors = $this->firstErrors;
        return reset($firstErrors) ?: 'Unknown Error.';
    }

    /**
     * {@inheritdoc}
     */
    public function load($data, $formName = '')
    {
        return parent::load($data, $formName);
    }
}